﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using VAdvantage.Utility;
using VAdvantage.Model;
using VAdvantage.Logging;
using System.Data;
using VAdvantage.Classes;
using VAdvantage.DataBase;
using System.Text;


namespace VAdvantage.Model
{
    public class MSession : X_AD_Session
    {
        /// <summary>
        /// Get existing or create local session
        /// </summary>
        /// <param name="ctx">context</param>
        /// <param name="createNew">create if not found</param>
        /// <returns>session</returns>
        public static MSession Get(Ctx ctx, Boolean createNew)
        {
            int AD_Session_ID = ctx.GetContextAsInt("#AD_Session_ID");
            MSession session = null;
            if (AD_Session_ID > 0)
                session = cache[AD_Session_ID];

            if (session == null && createNew)
            {
                session = new MSession(ctx, null);	//	local session
                session.Save();
                AD_Session_ID = session.GetAD_Session_ID();
                ctx.SetContext("#AD_Session_ID", AD_Session_ID.ToString());
                cache.Add(AD_Session_ID, session);
            }
            return session;
        }	//	get

        /// <summary>
        /// Get existing or create remote session
        /// </summary>
        /// <param name="ctx">context</param>
        /// <param name="Remote_Addr">remote address</param>
        /// <param name="Remote_Host">remote host</param>
        /// <param name="WebSession">web session</param>
        /// <returns>session</returns>
        public static MSession Get(Ctx ctx, String remoteAddr, String remoteHost, String WebSession)
        {
            int AD_Session_ID = ctx.GetContextAsInt("#AD_Session_ID");
            MSession session = null;
            if (AD_Session_ID > 0)
                session = cache[AD_Session_ID];
            if (session == null)
            {
                session = new MSession(ctx, remoteAddr, remoteHost, WebSession, null);	//	remote session
                session.Save();
                AD_Session_ID = session.GetAD_Session_ID();
                ctx.SetContext("#AD_Session_ID", AD_Session_ID.ToString());
                cache.Add(AD_Session_ID, session);
            }
            return session;
        }


        //	get
        /**	Sessions					*/
        private static CCache<int, MSession> cache = Ini.IsClient()
            ? new CCache<int, MSession>("AD_Session_ID", 1, 0)		//	one client session 
            : new CCache<int, MSession>("AD_Session_ID", 30, 0);	//	no time-out	


        /// <summary>
        /// 	 * 	Standard Constructor
        /// </summary>
        /// <param name="ctx">context</param>
        /// <param name="AD_Session_ID">id</param>
        /// <param name="trxName">transaction</param>
        public MSession(Ctx ctx, int AD_Session_ID, String trxName)
            : base(ctx, AD_Session_ID, trxName)
        {

            if (AD_Session_ID == 0)
            {
                SetProcessed(false);
                int AD_Role_ID = ctx.GetAD_Role_ID();
                SetAD_Role_ID(AD_Role_ID);
            }
        }	//	MSess

        /// <summary>
        /// Load Constructor
        /// </summary>
        /// <param name="ctx">context</param>
        /// <param name="rs">result set</param>
        /// <param name="trxName">transaction</param>
        public MSession(Ctx ctx, DataRow rs, String trxName)
            : base(ctx, rs, trxName)
        {

        }	//	MSession

        /// <summary>
        /// New (remote) Constructor
        /// </summary>
        /// <param name="ctx">context</param>
        /// <param name="Remote_Addr">remote address</param>
        /// <param name="Remote_Host">remote host</param>
        /// <param name="WebSession">web session</param>
        /// <param name="trxName">transaction</param>
        public MSession(Ctx ctx, String remoteAddr, String remoteHost, String webSession, String trxName)
            : this(ctx, 0, trxName)
        {

            if (remoteAddr != null)
                SetRemote_Addr(remoteAddr);
            if (remoteHost != null)
                SetRemote_Host(remoteHost);
            if (webSession != null)
                SetWebSession(webSession);
        }


        /// <summary>
        /// New (local) Constructor
        /// </summary>
        /// <param name="ctx">context</param>
        /// <param name="trxName">transaction</param>
        public MSession(Ctx ctx, String trxName)
            : base(ctx, 0, trxName)
        {

            //try
            //{
            //    //System.Net.Dns 1h=new System.Net.Dns(); 
            //    string hostName = System.Net.Dns.GetHostName();

            //    System.Net.IPAddress[] ipA = System.Net.Dns.GetHostAddresses(hostName);
            //    string cmpIP = "";
            //    for (int i = 0; i < ipA.Length; i++)
            //    {
            //        cmpIP = ipA[i].ToString();
            //    }
            //    //InetAddress lh = InetAddress.getLocalHost();
            //    SetRemote_Host(hostName);
            //    SetRemote_Addr(cmpIP);

            //}
            //catch (ApplicationException ex)
            //{
            //    log.Log(Level.SEVERE, "No Local Host", ex);
            //}
        }

        private Boolean _webStoreSession = false;

        public Boolean IsWebStoreSession()
        {
            return _webStoreSession;

        }

        public void SetWebStoreSession(Boolean webStoreSession)
        {
            _webStoreSession = webStoreSession;
        }	//	setWebStoreSession


        public void Logout()
        {
            SetProcessed(true);
            Save();
            cache.Remove(GetAD_Session_ID());
            //(GetAD_Session_ID());
            log.Info(TimeUtil.FormatElapsed(GetCreated(), GetUpdated()));
        }

        /// <summary>
        /// 	Create Change Log only if table is logged
        /// </summary>
        /// <param name="TrxName">transaction name</param>
        /// <param name="AD_ChangeLog_ID">0 for new change log</param>
        /// <param name="AD_Table_ID">table</param>
        /// <param name="AD_Column_ID">column</param>
        /// <param name="keyInfo">key value(s)</param>
        /// <param name="AD_Client_ID">client</param>
        /// <param name="AD_Org_ID">org</param>
        /// <param name="OldValue">old</param>
        /// <param name="NewValue">new</param>
        /// <param name="tableName"></param>
        /// <param name="type"></param>
        /// <returns>change log or null</returns>
        public MChangeLog ChangeLog(String trxName, int AD_ChangeLog_ID,
        int AD_Table_ID, int AD_Column_ID, Object keyInfo,
        int AD_Client_ID, int AD_Org_ID,
        Object oldValue, Object newValue,
        String tableName, String type)
        {
            //	Null handling
            if (oldValue == null && newValue == null)
                return null;
            //	Equal Value
            if (oldValue != null && newValue != null && oldValue.Equals(newValue))
                return null;

            //	No Log
            if (MChangeLog.IsNotLogged(AD_Table_ID, tableName, AD_Column_ID, type))
                return null;

            //	Role Logging
            MRole role = MRole.GetDefault(GetCtx(), false);
            //	Do we need to log
            if (_webStoreSession						//	log if WebStore
                || MChangeLog.IsLogged(AD_Table_ID, type)		//	im/explicit log
                || (role != null && role.IsChangeLog()))//	Role Logging
            { ;}
            else
            {
                return null;
            }
            //
            log.Finest("AD_ChangeLog_ID=" + AD_ChangeLog_ID
                    + ", AD_Session_ID=" + GetAD_Session_ID()
                    + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID
                   + ": " + oldValue + " -> " + newValue);
            Boolean success = false;

            try
            {
                MChangeLog cl = new MChangeLog(GetCtx(),
                    AD_ChangeLog_ID, trxName, GetAD_Session_ID(),
                    AD_Table_ID, AD_Column_ID, keyInfo, AD_Client_ID, AD_Org_ID,
                    oldValue, newValue);
                if (cl.Save())
                    return cl;
            }
            catch (Exception e)
            {
                log.Log(Level.SEVERE, "AD_ChangeLog_ID=" + AD_ChangeLog_ID
                    + ", AD_Session_ID=" + GetAD_Session_ID()
                    + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID, e);
                return null;
            }
            log.Log(Level.SEVERE, "AD_ChangeLog_ID=" + AD_ChangeLog_ID
               + ", AD_Session_ID=" + GetAD_Session_ID()
               + ", AD_Table_ID=" + AD_Table_ID + ", AD_Column_ID=" + AD_Column_ID);
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="AD_Client_ID"></param>
        /// <param name="AD_Org_ID"></param>
        /// <param name="AD_Table_ID"></param>
        /// <param name="whereClause"></param>
        /// <param name="recordCount"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public MQueryLog QueryLog(int AD_Client_ID, int AD_Org_ID,
        int AD_Table_ID, String whereClause, int recordCount, String parameter)
        {
            MQueryLog qlog = null;
            try
            {
                qlog = new MQueryLog(GetCtx(), GetAD_Session_ID(),
                    AD_Client_ID, AD_Org_ID,
                    AD_Table_ID, whereClause, recordCount, parameter);
                qlog.Save();
            }
            catch (Exception e)
            {
                log.Log(Level.SEVERE, "AD_Session_ID=" + GetAD_Session_ID()
                    + ", AD_Table_ID=" + AD_Table_ID + ", Where=" + whereClause
                   , e);
            }
            return qlog;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="AD_Client_ID"></param>
        /// <param name="AD_Org_ID"></param>
        /// <param name="AD_Table_ID"></param>
        /// <param name="whereClause"></param>
        /// <param name="recordCount"></param>
        /// <returns></returns>
        public MQueryLog QueryLog(int AD_Client_ID, int AD_Org_ID,
        int AD_Table_ID, String whereClause, int recordCount)
        {
            return QueryLog(AD_Client_ID, AD_Org_ID, AD_Table_ID,
                whereClause, recordCount, (String)null);
        }	//

        /// <summary>
        /// 
        /// </summary>
        /// <param name="AD_Client_ID"></param>
        /// <param name="AD_Org_ID"></param>
        /// <param name="AD_Table_ID"></param>
        /// <param name="whereClause"></param>
        /// <param name="recordCount"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public MQueryLog QueryLog(int AD_Client_ID, int AD_Org_ID,
        int AD_Table_ID, String whereClause, int recordCount, Object parameter)
        {
            String para = null;
            if (parameter != null)
                para = parameter.ToString();
            return QueryLog(AD_Client_ID, AD_Org_ID, AD_Table_ID,
                whereClause, recordCount, para);
        }	//

        /// <summary>
        /// 
        /// </summary>
        /// <param name="AD_Client_ID"></param>
        /// <param name="AD_Org_ID"></param>
        /// <param name="AD_Table_ID"></param>
        /// <param name="whereClause"></param>
        /// <param name="recordCount"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public MQueryLog QueryLog(int AD_Client_ID, int AD_Org_ID,
        int AD_Table_ID, String whereClause, int recordCount, Object[] parameters)
        {
            String para = null;
            if (parameters != null && parameters.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < parameters.Length; i++)
                {
                    if (i > 0)
                        sb.Append(", ");
                    if (parameters[i] == null)
                        sb.Append("NULL");
                    else
                        sb.Append(parameters[i].ToString());
                }
                para = sb.ToString();
            }
            return QueryLog(AD_Client_ID, AD_Org_ID, AD_Table_ID,
                whereClause, recordCount, para);
        }	//	queryLog

        /// <summary>
        /// 
        /// </summary>
        /// <param name="AD_Client_ID"></param>
        /// <param name="AD_Org_ID"></param>
        /// <param name="AD_Window_ID"></param>
        /// <param name="AD_Form_ID"></param>
        /// <returns></returns>
        public MWindowLog WindowLog(int AD_Client_ID, int AD_Org_ID,
        int AD_Window_ID, int AD_Form_ID)
        {
            MWindowLog wlog = null;
            try
            {
                wlog = new MWindowLog(GetCtx(), GetAD_Session_ID(),
                    AD_Client_ID, AD_Org_ID,
                    AD_Window_ID, AD_Form_ID);
                wlog.Save();
            }
            catch (Exception e)
            {
                log.Log(Level.SEVERE, "AD_Session_ID=" + GetAD_Session_ID()
                    + ", AD_Window_ID=" + AD_Window_ID + ", AD_Form_ID=" + AD_Form_ID
                    , e);
            }
            return wlog;
        }	//	windowLog

    }
}
